import { Buffer } from 'buffer'
import utils from './index.js'

function createBuffer(arg, arg2) {
  if (utils.isInteger(arg)) {
    return Buffer.allocUnsafe ? Buffer.allocUnsafe(arg) : new Buffer(arg)
  } else {
    return Buffer.from && Buffer.allocUnsafe ? Buffer.from(arg, arg2) : new Buffer(arg, arg2)
  }
}
function copyElements(src, i, dest, j, n, rev) {
  if (src === dest && j > i) utils.error("copy error")
  let inc = 1
  let offs = 0
  if (rev) {
    inc = -1
    offs = n - 1
  }
  for (let k = 0; k < n; k += 1, offs += inc) {
    dest[k + j] = src[i + offs]
  }
}

function extendBuffer(src, newLen, copyLen) {
  const len = Math.max(src.length, newLen)
  const n = copyLen || src.length
  const dest = new src.constructor(len)
  copyElements(src, 0, dest, 0, n)
  return dest
}
function mergeNames(name1, name2) {
  let merged = null
  if (name1 && name2) {
    merged = findStringPrefix(name1, name2).replace(/[-_]$/, '')
  }
  return merged || ''
}
function findStringPrefix(a, b) {
  let i = 0
  for (let n=a.length; i<n; i++) {
    if (a[i] !== b[i]) break
  }
  return a.substr(0, i)
}
function isFiniteNumber(val) {
  return val === 0 || !!val && val.constructor == Number && val !== Infinity && val !== -Infinity
}
function formatVersionedName(name, i) {
  let suffix = String(i)
  if (/[0-9]$/.test(name)) {
    suffix = '-' + suffix
  }
  return name + suffix
}
function uniqifyNames(names, formatter) {
  const counts = utils.countValues(names)
  const format = formatter || formatVersionedName
  const blacklist = {}

  Object.keys(counts).forEach((name) => {
    if (counts[name] > 1) blacklist[name] = true // uniqify all instances of a name
  })
  return names.map((name) => {
    let i = 1 // first version id
    let candidate = name
    while (candidate in blacklist) {
      const versionedName = format(name, i)
      if (!versionedName || versionedName == candidate) {
        throw new Error("Naming error") // catch buggy versioning function
      }
      candidate = versionedName
      i++
    }
    blacklist[candidate] = true
    return candidate
  })
}
export default {
  createBuffer,
  extendBuffer,
  mergeNames,
  isFiniteNumber,
  copyElements,
  formatVersionedName,
  uniqifyNames,
}